import 'dart:convert';
import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flui/flui.dart';
import 'package:flustars/flustars.dart';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:fzcgx_app/network/dio_log_intercepor.dart';
import 'package:fzcgx_app/network/http_entity.dart';
import 'package:fzcgx_app/network/urls.dart';
///网络请求成功,并且服务端code 返回值成功 object
typedef Success = Function<T>(T t);

///网络请求成功,并且服务端code 返回值成功 list
typedef ListSuccess = Function<T>(List<T> list);

///网络请求成功,服务端code 返回值失败
typedef Fail = Function(FailEntity failEntity);

///网络请求失败，无法连接服务器或者服务端返回的状态码不是200，可以统一处理
typedef Error = Function(ErrorEntity);

///网络请求完成
typedef Complete = Function();

class Http {
  static Http get instance => _getInstance();

  static Http _instance;

  Dio _dio;

  Http._internal() {
    if (_dio == null) {
      _dio = _initDio();
    }
  }

  // 静态、同步、私有访问点
  static Http _getInstance() {
    if (_instance == null) {
      _instance = new Http._internal();
    }
    return _instance;
  }

  int _timeout = 30000;

  Dio _initDio() {
    Dio dio = Dio(BaseOptions(
      connectTimeout: _timeout,
      receiveTimeout: _timeout,
      sendTimeout: _timeout,
      baseUrl: Urls.debug_base_url,
      responseType: ResponseType.plain,
    ));
    dio.interceptors
        .add(InterceptorsWrapper(onRequest: (RequestOptions options) async {
      dio.lock();

      var authorization = SpUtil.getString('token');
      options.headers["token"] = authorization;
      print('oo:' + authorization);
      // var banquetToken = await CacheDataManager.instance.getBanquetToken();
      // if (banquetToken != null && banquetToken.isNotEmpty) {
      //   options.headers["Cookie"] = 'Token=${Uri.encodeComponent(banquetToken)}';
      // }
      dio.unlock();
      return options;
    }));

    dio.interceptors
//      ..add(KLogInterceptor())
      ..add(PrettyDioLogger(
        requestBody: true,
        requestHeader: true,
      ));
    return dio;
  }

  /// get请求返回数据类型是object
  Future get<T>(String url, Map<String, dynamic> queryParameters,
      {Function(T) onSuccess,
      Fail onFail,
      Error onError,
      Complete complete,
      bool isBanquet = false}) {
    return _request<T>(
      'get',
      url,
      queryParameters,
      onSuccess: onSuccess,
      onFail: onFail,
      onError: onError,
      complete: complete,
    );
  }

  /// post请求返回数据类型是object
  Future post<T>(String url, data,
      {Function(T) onSuccess,
      Fail onFail,
      Error onError,
      Complete complete,
      ProgressCallback progressCallback,
      bool isBanquet = false}) {
    if (data == null) {
      data = Map();
      data['uid'] = SpUtil.getString('uid');
    } else {
      data['uid'] = SpUtil.getString('uid');
    }
    return _request<T>(
      'post',
      url,
      data,
      onSuccess: onSuccess,
      onFail: onFail,
      onError: onError,
      complete: complete,
      progressCallback: progressCallback,
    );
  }

  /// get请求返回数据类型是list
  Future getList<T>(String url, Map<String, dynamic> queryParameters,
      {Function(List<T>) onSuccess,
      Fail onFail,
      Error onError,
      Complete complete,
      bool isBanquet = false}) {
    return _requestList<T>(
      'get',
      url,
      queryParameters,
      onSuccess: onSuccess,
      onFail: onFail,
      onError: onError,
      complete: complete,
    );
  }

  /// post请求返回数据类型是list
  void postList<T>(
    String url,
    Map<String, dynamic> data, {
    Function(List<T>) onSuccess,
    Fail onFail,
    Error onError,
    Complete complete,
  }) {
    if (data == null) {
      data = Map();
      data['uid'] = SpUtil.getString('uid');
    } else {
      data['uid'] = SpUtil.getString('uid');
    }

    _requestList<T>(
      'post',
      url,
      data,
      onSuccess: onSuccess,
      onFail: onFail,
      onError: onError,
      complete: complete,
    );
  }

  /// 请求返回数据类型是object
  Future _request<T>(String method, String url, queryParameters,
      {Function(T) onSuccess,
      Fail onFail,
      Error onError,
      Complete complete,
      ProgressCallback progressCallback}) async {
    try {
      _dio.options.baseUrl =
          (kDebugMode ? Urls.debug_base_url : Urls.release_base_url);

      Response response = await _dio.request(url,
          queryParameters: method == 'get' ? queryParameters : null,
          data: method == 'post' ? queryParameters : null,
          options: Options(method: method),
          onSendProgress: progressCallback);
      if (response != null) {
        BaseEntity entity = BaseEntity<T>.fromJson(
          jsonDecode(_regExpData(response.data.toString())),
        );

        if (entity.code == 0) {
          if (onSuccess != null) {
            onSuccess(entity.data);
          }
        } else {
          if (entity.code == -1) {
            SpUtil.putString('uid', '');
            SpUtil.putString('token', '');
            
          }
          if (onFail != null) {
            onFail(FailEntity(code: entity.code, message: entity.message));
          }
          FLToast.showError(text: entity.message);
        }
      } else {
        if (onError != null) {
          onError(ErrorEntity(code: -1, message: '响应体为空'));
        }
      }

      if (complete != null) {
        complete();
      }
    } on DioError catch (e) {
      _httpError(onError, complete, e);
    } catch (e) {
      /// 解析过程中的异常
      print('数据解析异常: ${e.toString()}');
      if (onFail != null) {
        onFail(FailEntity(code: -2, message: '数据解析异常'));
      }

      if (complete != null) {
        complete();
      }
    }
  }

  /// get请求返回数据类型是object
  Future _requestList<T>(
    String method,
    String url,
    queryParameters, {
    Function(List<T>) onSuccess,
    Fail onFail,
    Error onError,
    Complete complete,
  }) async {
    try {
      _dio.options.baseUrl =
          kDebugMode ? Urls.debug_base_url : Urls.release_base_url;
      Response response = await _dio.request(url,
          queryParameters: method == 'get' ? queryParameters : null,
          data: method == 'post' ? queryParameters : null,
          options: Options(method: method));

      if (response != null) {
        BaseListEntity entity = BaseListEntity<T>.fromJson(
          jsonDecode(_regExpData(response.data.toString())),
        );

        if (entity.code == 0 || entity.code == 200) {
          if (onSuccess != null) {
            onSuccess(entity.data);
          }
        } else {
          if (entity.code == -1) {
            SpUtil.putString('uid', '');
            SpUtil.putString('token', '');
          }
          if (onFail != null) {
            onFail(FailEntity(code: entity.code, message: entity.message));
          }
        }
      } else {
        if (onError != null) {
          onError(ErrorEntity(code: -1, message: '响应体为空'));
        }
      }

      if (complete != null) {
        complete();
      }
    } on DioError catch (e) {
      _httpError(onError, complete, e);
    } catch (e) {
      /// 解析过程中的异常
      print('数据解析异常: ${e.toString()}');
      if (onFail != null) {
        onFail(FailEntity(code: -2, message: '数据解析异常'));
      }

      if (complete != null) {
        complete();
      }
    }
  }

  /// http错误
  void _httpError(onError, onComplete, DioError error) {
    if (onError != null) {
      switch (error.type) {
        case DioErrorType.CANCEL:
          {
            onError(ErrorEntity(code: -1, message: "请求取消"));
          }
          break;
        case DioErrorType.CONNECT_TIMEOUT:
          {
            onError(ErrorEntity(code: -1, message: "连接超时"));
          }
          break;
        case DioErrorType.SEND_TIMEOUT:
          {
            onError(ErrorEntity(code: -1, message: "请求超时"));
          }
          break;
        case DioErrorType.RECEIVE_TIMEOUT:
          {
            onError(ErrorEntity(code: -1, message: "响应超时"));
          }
          break;
        case DioErrorType.DEFAULT:
          {
            onError(ErrorEntity(code: -1, message: "请检查网络连接"));
          }
          break;
        case DioErrorType.RESPONSE:
          {
            try {
              onError(ErrorEntity(
                  code: error.response.statusCode, message: '请检查网络连接'));
            } on Exception catch (_) {
              onError(ErrorEntity(code: -1, message: "未知错误"));
            }
          }
          break;
        default:
          {
            onError(ErrorEntity(code: -1, message: error.message));
          }
      }
    }

    if (onComplete != null) {
      onComplete();
    }
  }

  ///替换一些特殊字符
  String _regExpData(String data) {
    return (data ?? '').replaceAllMapped(RegExp(r'[\t\v]'), (match) => '');
  }

  ///上传图片
  Future<T> uploadImage<T>(String url, String path,
      {ProgressCallback progressCallback,
      Complete complete,
      bool isBanquet = false}) async {
    var file = File(path);
    var bool = await file.exists();

    if (!bool) {
      return Future.value(null);
    }

    String fileName = path.substring(path.lastIndexOf("/") + 1);
    debugPrint("fileName ：$fileName");
    debugPrint("fileSize ：${file.lengthSync()}");

    var formData = FormData.fromMap({
      'file': await MultipartFile.fromFile(path, filename: fileName),
    });

    T result;
    await Http.instance.post<T>(url, formData,
        progressCallback: progressCallback,
        isBanquet: isBanquet, onSuccess: (data) {
      result = data;
    }, onError: (error) {}, onFail: (fail) {});

//    var image = Image.file(file);
//    // 预先获取图片信息
//    image.image.resolve(new ImageConfiguration()).addListener(new ImageStreamListener((info, _) async {
//      var width = info.image.width;
//      var height = info.image.height;
//      debugPrint("宽：$width");
//      debugPrint("高：$height");
//
//
//    }));

    return result;
  }
}
